package com.hsmpay.yl8583.service;

import com.hsmpay.utils.DesUtil;
import com.hsmpay.utils.NumberUtil;
import com.hsmpay.utils.TimeUtils;
import com.hsmpay.utils.WriteFile;
import com.hsmpay.utils.system.ConConfig;
import com.hsmpay.yl8583.utils.TestDes;
import com.iso8583.Iso8583Composer;
import com.iso8583.Iso8583Parser;
import com.iso8583.util.ByteUtils;
import com.iso8583.util.J8583Util;
import com.iso8583.util.PosUtil;
import org.apache.commons.lang.StringUtils;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by zhy on 15/11/10.
 */
public class PosToBoss {
    static WriteFile wf = new WriteFile("ds_pos");
    public static String debug = ConConfig.getAttribute("POS_DAISHOU_DEBUG_STATUS");
    //大pos通道参数信息
    static String ipAddr = "118.145.2.70";
    static String port = "27500";
    private String operator = "001";
    String shopCode = "";//商户号
    String posNo = "";//终端号
    String tpdu = "6000030000";
    String header = "601010100000";
    String batch = "000001";
    String mainKey = "";
    String muKey = "";
    String pinKey = "";
    String macKey = "";
    String trkKey = "";
    String sensKey = "";//敏感信息秘钥
    //pos通道生产环境 地址和端口号
    static{
        ipAddr = "118.145.2.70";
        port = "27500";
    }


    /**
     *
     * @param merchantId
     * @param terminalId
     * @param batch
     * @param muKey 解密秘钥
     * @param mainKey 加密的终端主密钥
     * @param pinKey
     * @param macKey
     * @param trkKey
     */
    public PosToBoss(String merchantId, String terminalId, String batch, String muKey, String mainKey, String pinKey, String macKey, String trkKey, String sensKey){
        if (StringUtils.isNotBlank(muKey) && StringUtils.isNotBlank(mainKey)){
            this.mainKey = DesUtil.decode3DES(mainKey, muKey);
        }
        this.shopCode = merchantId;
        this.posNo = terminalId;
        this.muKey = muKey;
        this.pinKey = pinKey;
        this.macKey = macKey;
        this.trkKey = trkKey;
        if (StringUtils.isNotBlank(muKey) && StringUtils.isNotBlank(mainKey) && StringUtils.isNotBlank(sensKey)){
            String masterKey = DesUtil.decode3DES(mainKey, muKey);
            this.sensKey = DesUtil.decode3DES(sensKey, masterKey);//使用解密后的masterKey解密sensKey
        }
        if (StringUtils.isNotEmpty(batch)){
            this.batch = batch;
        }else{
            this.batch = "000001";
        }


        wf.log("tpdu:" + this.tpdu, "调试");
        wf.log("ShopCode(商户号):" + this.shopCode, "调试");
        wf.log("PosNo(终端号):" + this.posNo, "调试");
        wf.log("batch(批次号):" + this.batch, "调试");
        wf.log("MuKey:" + this.muKey, "调试");//数据库保存是 主秘钥
        wf.log("mainKey:" + this.mainKey, "调试");
        wf.log("PinKey:" + this.pinKey, "调试");
        wf.log("MacKey:" + this.macKey, "调试");
        wf.log("trkKey:" + this.trkKey, "调试");
    }

    /**
     * 终端签到
     * @param serialNumber 流水号(11域)
     * @return 批次号
     * @throws Exception
     */
    public String Login0800(String serialNumber) throws Exception {
        String LoginMsg = "0";
        String TYPE_ID = "0800";
        String mustFields = "";
        HashMap<String,String> body = new HashMap<String,String>();
        wf.log("-------------------请求包域值信息-------------------", "调试");
        body.put("TPDU", this.tpdu);
        body.put("HEAD", this.header);
        body.put("CSEQ_NO", serialNumber);
        body.put("TRM_NO", this.posNo);
        body.put("MERC_CD", this.shopCode);
        body.put("F47", "SI=13|SN=61112015232211|TP=SCL8300|CT=2");
        body.put("RESE_PRI_60", "00" + this.batch + "003");
        body.put("RESE_PRI_63",this.operator);
        String optionalFields = "11|41|42|47|60|63";
        //生成报文
        System.out.println("大pos签到生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optionalFields, TYPE_ID, body, "POSADVANCE", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage, false);//此处false代表加不加空格
        wf.log("大pos签到请求报文为：" + req, "调试");
        System.out.println("pos签到请求报文为：" + req);
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ipAddr, Integer.valueOf(port));
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("大pos签到响应报文是：" + res);
        wf.log("大pos签到响应报文为：" + res, "调试");
        try {
            //解析报文
            byte[] bytes = ByteUtils.hexStringToByte(res);
            Map<String, String> map = Iso8583Parser.parse("POSADVANCE", bytes, true);
            //处理解析的map
            //分别获取39,60,62域
            String bit39 = map.get("39");
            if ("00".equals(bit39)){
                //截取60域批次号部分
                String bit62 = map.get("62");
                String MASTERKEY = bit62.substring(0, 32);//加密的终端主密钥
                String MASTERKEY_CHECK = bit62.substring(32,40);//终端主密钥验证码
                String PINKEY = bit62.substring(40,72);//加密的pin秘钥
                String PINKEY_CHECK = bit62.substring(72,80);//pin秘钥的验证码
                String MACKEY = bit62.substring(80, 112);
                String MACKEY_CHECK = bit62.substring(112, 120);
                String TRACKKEY = bit62.substring(120, 152);
                String TRACKKEY_CHECK = bit62.substring(152, 160);
                String SENSITIVEKEY = bit62.substring(160, 192);//加密的敏感信息秘钥
                String SENSITIVEKEY_CHECK = bit62.substring(192,200);//敏感信息秘钥的验证码
                //从60域中获取批次信息
                String bit60 = map.get("60");
                String receiveBatch;
                if (StringUtils.isNotBlank(bit60)){
                    receiveBatch = bit60.substring(2,8);
                }else{
                    receiveBatch = this.batch;
                }
                LoginMsg = "0_"+ bit39+ "_" + receiveBatch + "_"+ MASTERKEY +"_" + PINKEY + "_" + MACKEY + "_" + TRACKKEY + "_" + SENSITIVEKEY;

            }else {
                LoginMsg = "0_" + bit39;
            }
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("大pos签到返回报文解析报文错误");
            wf.log("大pos签到返回报文解析错误" ,"调试");
        }
        return LoginMsg;
    }

    /**
     * 银行卡余额查询
     *
     * @param trk2 二磁道数据
     * @param trk3 二磁道数据
     * @param pin  卡交易密码
     * @param accountNumber 主账号
     * @param serialNumber 受卡方系统跟踪号
     * @return 订单信息
     * @throws Exception
     */
    public String Query(String trk2, String trk3, String pin, String accountNumber, String serialNumber, String bit23, String bit55, String bit14) throws Exception {
        //String des_pin = Des3.encryptPin(accountNumber, pin, "5CF180B0BAB52DAACDA295241C0D39E4");
        Date date = new Date();
        String temp53 = TimeUtils.getDateTime(date, "ddHHmmss") + NumberUtil.getHexRandomCode(8);
        String des_pin = TestDes.PosEncryptPin(temp53, pin, pinKey, mainKey, date);//不需要主账号
        String QueryMsg = "";
        String TYPE_ID = "0200";
        String mustFields = "";
        StringBuffer optionalFields = new StringBuffer("");
        HashMap<String,String> body = new HashMap<String,String>();
        wf.log("-------------------请求包域值信息-------------------", "调试");
        body.put("TPDU", this.tpdu);
        body.put("HEAD", this.header);
        //第2 61 62域敏感信息域
//        String temp2 = TestDes.encryptSpecial(temp53, accountNumber, sensKey, date);
//        body.put("PAN", temp2);
//        optionalFields.append("2|");
        body.put("PRO_COD", "310000");
        optionalFields.append("3|");
        body.put("CSEQ_NO", serialNumber);
        System.out.println("pos终端流水号：" + serialNumber);
        optionalFields.append("11|");
        if (!"".equals(bit14.trim())) {
            body.put("EXP_DT", bit14);
            optionalFields.append("14|");
        }
        if ("".equals(bit55.trim())) {
            body.put("IN_MOD", "021");
            optionalFields.append("22|");
        }else {
            body.put("IN_MOD", "051");
            optionalFields.append("22|");
        }
        if (!"".equals(bit23.trim())) {
            body.put("SEP_NUM", bit23);
            optionalFields.append("23|");
        }
        body.put("CON_MOD", "00");
        optionalFields.append("25|");
        body.put("PIN_CAP_CODE", "06");
        optionalFields.append("26|");
        if (!"".equals(trk2.trim())) {
            System.out.println("加密前的trk2为：" + trk2);
            //对后16位加密
            trk2 = TestDes.PosEncryptTrack(temp53, trkKey, mainKey, trk2, date);
            //替换掉原trk 数据的后16位
            body.put("TRACK_2", trk2);
            System.out.println("加密截取后的trk2为：" + trk2);
            optionalFields.append("35|");
        }
        if (!"".equals(trk3.trim())) {
            trk3 = TestDes.PosEncryptTrack(temp53, trkKey, mainKey, trk3, date);
            body.put("TRACK_3", trk3);
            optionalFields.append("36|");
        }
        body.put("TRM_NO", this.posNo);
        optionalFields.append("41|");
        body.put("MERC_CD", this.shopCode);
        optionalFields.append("42|");
        body.put("F47", "SI=13|SN=61112015232211|TP=SCL8300|CT=2");
        optionalFields.append("47|");
        body.put("CCY", "156");
        optionalFields.append("49|");
        body.put("PIN_DATA", des_pin);
        optionalFields.append("52|");
        body.put("SECUR_INF", temp53);
        optionalFields.append("53|");
        if (!"".equals(bit55.trim())) {
            body.put("IC_DAT", bit55);
            optionalFields.append("55|");
        }
        if ("".equals(bit55.trim())) {
            body.put("RESE_PRI_60", "01" + this.batch);
            optionalFields.append("60|");
        }else {
            body.put("RESE_PRI_60", "01" + this.batch + "00050");
            optionalFields.append("60|");
        }
//        body.put("RESE_PRI_63",this.operator);
//        optionalFields.append("63|");
        body.put("F64", "");
        optionalFields.append("64");
        Iso8583Composer com = new Iso8583Composer();
        byte[] MacMessage = com.compose(mustFields, optionalFields.toString(), TYPE_ID, body, "POSADVANCE", true);
        String request = ByteUtils.byte2HexStr(MacMessage,false);
        String sub = request.substring(22,request.length()-16);
        String macstr = TestDes.encryptPOSMac(temp53, macKey, sub, mainKey, date);//加密操作,传参问题
        body.put("F64", macstr);
        System.out.println("optionalFields " + optionalFields.toString());
        //生成报文
        System.out.println("大pos查询余额生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optionalFields.toString(), TYPE_ID, body, "POSADVANCE", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        wf.log("大pos查询余额请求报文为：" + req, "调试");
        System.out.println("大pos查询余额请求报文为：" + req);
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ipAddr, Integer.valueOf(port));
        String res = ByteUtils.byte2HexStr(response, false);
        if ((!"-1".equals(res)) && (!"".equals(res))) {
            System.out.println("大pos查询余额响应报文是：" + res);
            wf.log("大pos查询余额响应报文为：" + res, "调试");
            try {
                PosUtil.parse8583("POSADVANCE", res);
                //解析报文
                Map<String, String> map = Iso8583Parser.parse("POSADVANCE", response, true);
                //获取39、54域
                String result39 = map.get("39");
                if ("00".equals(result39)){
                    String result54 = map.get("54");
                    String AmountStr = handle54(result54);
                    QueryMsg = "0" + "_" + result39 + "_" + AmountStr;
                }else {
                    QueryMsg = "0" + "_" + result39;
                }
                //获取域值信息，处理返回数据
            }catch (Exception e) {
                e.printStackTrace();
                System.out.println("大pos查询余额解析错误");
                wf.log("大pos查询余额解析错误", "调试");
            }
        }else {
            QueryMsg = "-1_";
        }
        wf.log("大pos佘额查询返回数据:" + QueryMsg, "调试");
        return QueryMsg;
    }
    /**
     * 处理54域信息的方法
     */
    public String  handle54(String field54){
        String AmountStr = "";
        if (field54.length()== 20) {
            AmountStr = handleMoney(field54);
        }else{
            AmountStr = handleMoney(field54.substring(0, 20));
        }
        return AmountStr;
    }
    private String handleMoney(String field54){
        String AmountStr = "";
        String ACCOUNT_TYPE = "";        //帐户类型(10:储蓄帐户,30:信用卡帐户)
        //String AMOUNT_TYPE="";		//数量类型(02:可用佘额)
        String CURRENCY_CODE = "";    //货币代码(156:人民币,其它:美元)
        String AMOUNT_SIGN = "";        //余额符号(C:正,其它:负)
        Double AMOUNT = 0.00;            //佘额(12位表示,分为单位)
        ACCOUNT_TYPE = field54.substring(0, 2);
        //AMOUNT_TYPE=value.substring(2, 4);
        CURRENCY_CODE = field54.substring(4, 7);
        AMOUNT_SIGN = field54.substring(7, 8);
        AMOUNT = Double.parseDouble(field54.substring(8)) / 100;
        if (ACCOUNT_TYPE.equals("10")) {
            AmountStr += "储蓄帐户 ";
        } else if (ACCOUNT_TYPE.equals("30")) {
            AmountStr += "信用卡帐户 ";
        }
        if (CURRENCY_CODE.equals("156")) {
            AmountStr += "￥";
        } else {
            AmountStr += "$";
        }
        if (!AMOUNT_SIGN.equals("C")) {
            AmountStr += "-";
        }
        AmountStr += AMOUNT;
        return AmountStr;
    }
    /**
     * 消费
     *
     * @param trk2          二磁道数据
     * @param trk3          三磁道数据
     * @param pin           密码
     * @param money         交易金额
     * @param accountNumber 卡号
     * @param serialNumber  订单号
     * @param bit23         IC卡序列号
     * @param bit55         IC卡 55 域
     * @param bit14         IC卡 序列号
     * @return 返回消费相关信息
     * @throws Exception
     */
    public String BillPayment(String trk2, String trk3, String pin, String money, String accountNumber, String serialNumber, String bit23, String bit55, String bit14) throws Exception {
        Date date = new Date();
        String temp53 = TimeUtils.getDateTime(date, "ddHHmmss") + NumberUtil.getHexRandomCode(8);
        String des_pin = TestDes.PosEncryptPin(temp53, pin, pinKey, mainKey, date);//不需要主账号
        String comsumeMsg = "";
        String TYPE_ID = "0200";
        String mustFields = "";
        StringBuffer optionalFields = new StringBuffer("");
        HashMap<String,String> body = new HashMap<String,String>();
        wf.log("-------------------请求包域值信息-------------------", "调试");
        body.put("TPDU", this.tpdu);
        body.put("HEAD", this.header);
        //第2 61 62域要加密
//        String temp2 = TestDes.encryptSpecial(temp53, accountNumber, sensKey, date);
//        body.put("PAN", temp2);
//        optionalFields.append("2|");
        body.put("PRO_COD", "000000");
        optionalFields.append("3|");
        body.put("TTXN_AMT", money);
        optionalFields.append("4|");
        body.put("CSEQ_NO", serialNumber);
        optionalFields.append("11|");
        if (!"".equals(bit14.trim())) {
            body.put("EXP_DT", bit14);
            optionalFields.append("14|");
        }
        if ("".equals(bit55.trim())) {
            body.put("IN_MOD", "021");
            optionalFields.append("22|");
        }else {
            body.put("IN_MOD", "051");
            optionalFields.append("22|");
        }
        if (!"".equals(bit23.trim())) {
            body.put("SEP_NUM", bit23);
            optionalFields.append("23|");
        }
        body.put("CON_MOD", "00");
        optionalFields.append("25|");
        body.put("PIN_CAP_CODE", "12");
        optionalFields.append("26|");
        if (!"".equals(trk2.trim())) {
            System.out.println("trk2....." + trk2);
            trk2 = TestDes.PosEncryptTrack(temp53, trkKey, mainKey, trk2, date);
            body.put("TRACK_2", trk2);
            optionalFields.append("35|");
        }
        if (!"".equals(trk3.trim())) {
            trk3 = TestDes.PosEncryptTrack(temp53, trkKey, mainKey, trk3, date);
            body.put("TRACK_3", trk3);
            optionalFields.append("36|");
        }
        body.put("TRM_NO", this.posNo);
        optionalFields.append("41|");
        body.put("MERC_CD", this.shopCode);
        optionalFields.append("42|");
        body.put("F47", "SI=13|SN=61112015232211|TP=SCL8300|CT=2");
        optionalFields.append("47|");
        body.put("CCY", "156");
        optionalFields.append("49|");
        body.put("PIN_DATA", des_pin);
        optionalFields.append("52|");
        body.put("SECUR_INF", temp53);
        optionalFields.append("53|");
        if (!"".equals(bit55.trim())) {
            body.put("IC_DAT", bit55);
            optionalFields.append("55|");
        }
        if ("".equals(bit55.trim())) {
            body.put("RESE_PRI_60", "22" + this.batch);
            optionalFields.append("60|");
        }else {
            body.put("RESE_PRI_60", "22" + this.batch + "00050");
            optionalFields.append("60|");
        }
//        body.put("RESE_PRI_63", this.operator);
//        optionalFields.append("63|");
        body.put("F64", "");
        optionalFields.append("64");
        Iso8583Composer com = new Iso8583Composer();
        byte[] MacMessage = com.compose(mustFields, optionalFields.toString(), TYPE_ID, body, "POSADVANCE", true);
        String request = ByteUtils.byte2HexStr(MacMessage,false);
        String sub = request.substring(22,request.length()-16);
        //63域是否要出现
        String macstr = TestDes.encryptPOSMac(temp53, macKey, sub, mainKey, date);//加密操作,传参问题
        body.put("F64", macstr);
        System.out.println("optionalFields " + optionalFields.toString());
        //生成报文
        System.out.println("大pos消费生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optionalFields.toString(), TYPE_ID, body, "POSADVANCE", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        wf.log("大pos消费请求报文为：" + req, "调试");
        System.out.println("大pos消费请求报文为：" + req);
        //发送请求报文，并且返回响应
        System.out.println("ipAdd" + ipAddr + "--------------------" + "IPort" + port);
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ipAddr, Integer.valueOf(port));
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("大pos消费响应报文是：" + res);
        wf.log("大pos消费响应报文为：" + res, "调试");
        try {
            PosUtil.parse8583("POSADVANCE", res);
            //解析报文,返回解析的域map
            Map<String, String> map = Iso8583Parser.parse("POSADVANCE", response, true);
            //需要获取2,4,11,12,13,14,37,38,39域信息
            String result2 = map.get("2");
            String result4 = map.get("4");
            String result11 = map.get("11");
            String result12 = map.get("12");
            String result13 = map.get("13");
            String result14 = map.get("14");
            String result37 = map.get("37");
            String result38 = map.get("38");
            String result39 = map.get("39");
            comsumeMsg = "0_" + result2 + "_" +result4 + "_" +result11 + "_" + result12 + "_" +result13 + "_" + result14 + "_" +result37 + "_" +result38 +"_"+result39;
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("大pos消费响应报文解析错误");
            wf.log("大pos消费响应报文解析错误", "调试");
        }
        wf.log("大pos消费返回数据:" + comsumeMsg, "调试");
        return comsumeMsg;
    }
    /**
     * 消费冲正（交易）
     *
     * @param trk2 二磁道数据
     * @param trk3 三磁道数据
     * @return 订单信息
     * @throws Exception
     */
    public String unBillPayment(String pin, String trk2, String trk3, String money, String accountNumber, String serialNumber, String newSerial, String bit38, String bit23, String bit55, String bit14, String bit39) throws Exception {
        Date date = new Date();
        String temp53 = TimeUtils.getDateTime(date, "ddHHmmss") + NumberUtil.getHexRandomCode(8);
        String des_pin = TestDes.PosEncryptPin(temp53, pin, pinKey, mainKey, date);//不需要主账号
        String QueryMsg = "";
        String typeCode = "0400";//消息类型
        String mustFields = "";
        StringBuffer optinalFields = new StringBuffer("");
        HashMap<String, String> body = new HashMap<String, String>();
        body.put("TPDU", this.tpdu);
        body.put("HEAD",this.header);
        //第2 61 62域敏感区域要加密
//        String res2 = TestDes.encryptSpecial(temp53, accountNumber, sensKey, date);
//        body.put("PAN", res2);
//        optinalFields.append("2|");
        body.put("PRO_COD", "000000");//交易处理码 3
        optinalFields.append("3|");
        body.put("TTXN_AMT", money);//交易金额 4
        optinalFields.append("4|");
        body.put("CSEQ_NO", newSerial);
        optinalFields.append("11|");
        if (StringUtils.isNotBlank(bit55)){
            body.put("EXP_DT",bit14);
            optinalFields.append("14|");
        }
        if ("".equals(bit55.trim())) {//服务点输入方式码 22
            body.put("IN_MOD", "021");
            optinalFields.append("22|");
        }else {
            body.put("IN_MOD", "051");
            optinalFields.append("22|");
        }
        if (!"".equals(bit23.trim())) {
            body.put("SEP_NUM", bit23);
            optinalFields.append("23|");
        }
        body.put("CON_MOD", "00");//服务点条件码 25
        optinalFields.append("25|");
//        body.put("PIN_CAP_CODE", "06");
//        optinalFields.append("26|");//服务点PIN获取码 26
        if (!"".equals(trk2.trim())) {
            System.out.println("trk2....." + trk2);
            trk2 = TestDes.PosEncryptTrack(temp53, trkKey, mainKey, trk2, date);
            body.put("TRACK_2", trk2);
            optinalFields.append("35|");
        }
        if (!"".equals(trk3.trim())) {
            trk3 =  TestDes.PosEncryptTrack(temp53, trkKey, mainKey, trk3, date);
            body.put("TRACK_3", trk3);
            optinalFields.append("36|");
        }
        //38域需要判断应答码中是否存在
        if (StringUtils.isNotBlank(bit38)){
            body.put("AUT_CD", bit38);
            optinalFields.append("38|");
        }
        //授权标识应答码 38 如果原始交易的应答中有授权码，则须填入原交易授权码 从响应报文中获取
//        body.put("CPSCOD","");//应答码 39 请求时为冲正原因，见注  交易报文中获取
//        optinalFields.append("39|");
        body.put("TRM_NO", this.posNo);//受卡机终端标识码 41 同原消费交易
        optinalFields.append("41|");
        body.put("MERC_CD", this.shopCode);//受卡方标识码 42
        optinalFields.append("42|");
        body.put("F47", "SI=13|SN=61112015232211|TP=SCL8300|CT=2");
        optinalFields.append("47|");
        body.put("CCY", "156");//交易货币代码 49
        optinalFields.append("49|");
        body.put("PIN_DATA", des_pin);
        optinalFields.append("52|");
        body.put("SECUR_INF", temp53);
        optinalFields.append("53|");
        if (!"".equals(bit55.trim())) {
            body.put("IC_DAT", bit55);
            optinalFields.append("55|");
        }
        if ("".equals(bit55.trim())) {
            body.put("RESE_PRI_60", "23" + this.batch);
            optinalFields.append("60|");
        }else {
            body.put("RESE_PRI_60", "23" + this.batch + "00050");
            optinalFields.append("60|");
        }
        //61域 原批次号,原流水号 敏感信息域
        String bit61 = this.batch + serialNumber;
        String res61 = TestDes.encryptSpecial(temp53, bit61, sensKey, date);
        body.put("ORI_MES", res61);
        optinalFields.append("61|");
//        body.put("RESE_PRI_63", this.operator);
//        optinalFields.append("63|");
        body.put("F64", "");
        optinalFields.append("64");
        Iso8583Composer com = new Iso8583Composer();
        byte[] MacMessage = com.compose(mustFields, optinalFields.toString(), typeCode, body, "POSADVANCE", true);
        String request = ByteUtils.byte2HexStr(MacMessage,false);
        String sub = request.substring(22,request.length()-16);
        String macstr = TestDes.encryptPOSMac(temp53, this.macKey, sub, this.mainKey, date);//加密操作,传参问题
        body.put("F64", macstr);
        System.out.println("optionalFields " + optinalFields.toString());
        //生成报文
        System.out.println("大pos消费冲正生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optinalFields.toString(), typeCode, body, "POSADVANCE", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        wf.log("大pos消费冲正请求报文为：" + req, "调试");
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ipAddr, Integer.valueOf(port));
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("大pos消费冲正响应报文是：" + res);
        wf.log("大pos消费冲正响应报文为：" + res, "调试");
        try {
            PosUtil.parse8583("POSADVANCE", res);
            //解析报文
            byte[] bytes = ByteUtils.hexStringToByte(res);
            Map<String, String> map = Iso8583Parser.parse("POSADVANCE", bytes, true);
            //处理2,4,11,12,13,14,37,38,39,44,61域信息
            String temp2 = map.get("2");
            String temp4 = map.get("4");
            String temp11 = map.get("11");
            String temp12 = map.get("12");
            String temp13 = map.get("13");
            String temp14 = map.get("14");
            String temp37 = map.get("37");
            String temp38 = map.get("38");
            String temp39 = map.get("39");
            String temp44 = map.get("44");
            String temp61 = map.get("61");
            QueryMsg = temp2+"_"+temp4+"_"+temp11+"_"+temp12+"_"+temp13+"_"+temp14+"_"+temp37+"_"+temp38+"_"+temp39+"_"+temp44+"_"+temp61;
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("大pos消费冲正响应报文解析错误");
            wf.log("大pos消费冲正响应报文解析错误", "调试");
        }
        wf.log("大pos消费冲正返回数据:" + QueryMsg, "调试");
        return QueryMsg;
    }
    public static void main(String[] argus) throws Exception {
          //解码
//        String mac = "09DB7567";
//        System.out.println(DesUtil.byte2hex(mac.getBytes()));
//        String mukey = "5d22b55aa2bfae9df19d94b140f54344";
//        String mainKey = "392E20C51289CBA132C41D8174A23B6E";
//        String masterKey = DesUtil.decode3DES(mainKey, mukey);
//        System.out.println("masterKey: " + masterKey);
//        String macKey = "A5BDFE6304318A458A629E76E9925DDA";
//        String decodedMacKey = DesUtil.decode3DES(macKey, masterKey);
//        System.out.println("decodedMacKey: " + decodedMacKey);
          //撤销
          cancel();
    }

    /**
     * 查询
     */
    public static void search(){
        Date date = new Date();
        String ip = "118.145.2.70";
        Integer port = 27500;
        String tpdu = "6000030000";
        String header = "602100000000";
        String posNo = "3AA408D3";
        String shopCode = "173665654105665";
        String batch = "000001";
        String TYPE_ID = "0200";
        String mustFields = "";
        HashMap<String,String> body = new HashMap<String,String>();
        wf.log("-------------------请求包域值信息-------------------", "调试");
        body.put("TPDU", tpdu);
        body.put("HEAD", header);
        //body.put("PAN","6210676802072012504");//2
        body.put("PRO_COD","310000");//3
        body.put("TTXN_AMT","000000666666");//4
        body.put("CSEQ_NO","000002");//11
        body.put("IN_MOD","021");//22
        body.put("CON_MOD","00");//25
        body.put("PIN_CAP_CODE","12");//26
        body.put("TRACK_2","E40A5C810A840665E50AD84F34F961B350000");//35
        //body.put("TRACK_3","");//36
        body.put("TRM_NO", posNo);//41
        body.put("MERC_CD", shopCode);//42
        body.put("F47","SI=13|SN=61112015232211|TP=SCL8300|CT=2");//47
        body.put("CCY","156");//49
        body.put("PIN_DATA","63C07D240ED468D5");//52
        String temp53 = "171028147D05D8EB";
        body.put("SECUR_INF", temp53);//53
        body.put("RESE_PRI_60", "01" + batch);//60
        //body.put("RESE_PRI_63","001");//63
        body.put("F64","");//64
        String optionalFields = "3|11|22|25|26|35|41|42|47|49|52|53|60|64";
        String comsumeMsg;
        //生成报文
        Iso8583Composer com = new Iso8583Composer();
        byte[] MacMessage = com.compose(mustFields, optionalFields.toString(), TYPE_ID, body, "POSADVANCE", true);
        String request = ByteUtils.byte2HexStr(MacMessage, false);
        String sub = request.substring(22,request.length()-16);
        String macKey = "";//TODO:还得运算
        String mainKey = "";//TODO:还得运算
        String macstr = TestDes.encryptPOSMac(temp53, macKey, sub, mainKey, date);//加密操作,传参问题
        body.put("F64", macstr);
        System.out.println("optionalFields " + optionalFields.toString());
        //生成报文
        System.out.println("大pos消费生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optionalFields.toString(), TYPE_ID, body, "POSADVANCE", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        wf.log("大pos消费请求报文为：" + req, "调试");
        System.out.println("大pos消费请求报文为：" + req);
        //发送请求报文，并且返回响应
        System.out.println("ipAdd" + ipAddr + "--------------------" + "IPort" + port);
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ipAddr, Integer.valueOf(port));
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("大pos消费响应报文是：" + res);
        wf.log("大pos消费响应报文为：" + res, "调试");
        try {
            PosUtil.parse8583("POSADVANCE", res);
            //解析报文,返回解析的域map
            Map<String, String> map = Iso8583Parser.parse("POSADVANCE", response, true);
            //需要获取2,4,11,12,13,14,37,38,39域信息
            String result2 = map.get("2");
            String result4 = map.get("4");
            String result11 = map.get("11");
            String result12 = map.get("12");
            String result13 = map.get("13");
            String result14 = map.get("14");
            String result37 = map.get("37");
            String result38 = map.get("38");
            String result39 = map.get("39");
            comsumeMsg = "0_" + result2 + "_" +result4 + "_" +result11 + "_" + result12 + "_" +result13 + "_" + result14 + "_" +result37 + "_" +result38 +"_"+result39;
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("大pos消费响应报文解析错误");
            wf.log("大pos消费响应报文解析错误", "调试");
        }
    }

    /**
     * 签到
     */
    public static void sign(){
        String ip = "118.145.2.70";
        Integer port = 27500;
        String tpdu = "6000030000";
        String header = "603100310101";
        String posNo = "3AA408D3";
        String shopCode = "173665654105665";
        String batch = "000001";
        String TYPE_ID = "0800";
        String mustFields = "";
        HashMap<String,String> body = new HashMap<String,String>();
        wf.log("-------------------请求包域值信息-------------------", "调试");
        body.put("TPDU", tpdu);
        body.put("HEAD", header);
        body.put("CSEQ_NO","134641");
        body.put("TRM_NO", posNo);
        body.put("MERC_CD", shopCode);
        body.put("F47","SI=13|SN=61112015232211|TP=SCL8300|CT=2");
        body.put("RESE_PRI_60", "00" + batch + "003");
        body.put("RESE_PRI_63","001");
        String optionalFields = "11|41|42|47|60|63";
        //生成报文
        System.out.println("大pos签到生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optionalFields, TYPE_ID, body, "POSADVANCE", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage, false);//此处false代表加不加空格
        wf.log("大pos签到请求报文为：" + req, "调试");
        System.out.println("pos签到请求报文为：" + req);
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ip, port);
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("大pos签到响应报文是：" + res);
        wf.log("大pos签到响应报文为：" + res, "调试");
        try {
            //解析报文
            byte[] bytes = ByteUtils.hexStringToByte(res);
            Map<String, String> map = Iso8583Parser.parse("POSADVANCE", bytes, true);
            PosUtil.parse8583("POSADVANCE", res);
            //处理解析的map
            //分别获取39,60,62域
            String bit39 = map.get("39");
            if ("00".equals(bit39)){
                //截取60域批次号部分
                String bit60 = map.get("60");
                String receiveBatch = bit60.substring(2,8);
                String bit62 = map.get("62");
                System.out.println("签到返回的报文为: " + bit62);
            }else {
                System.out.println("返回的39域为: " + bit39);
            }
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("大pos签到返回报文解析报文错误");
            wf.log("大pos签到返回报文解析错误" ,"调试");
        }
    }

    /**
     * 撤销
     */
    public static void cancel(){
        String ip = "118.145.2.70";
        Integer port = 27500;
        String tpdu = "6000030000";
        String header = "601010100000";
        String posNo = "3AA408D3";
        String shopCode = "173665654105665";
        String batch = "000001";
        String TYPE_ID = "0200";
        String mustFields = "";
        HashMap<String,String> body = new HashMap<String,String>();
        wf.log("-------------------请求包域值信息-------------------", "调试");
        body.put("TPDU", tpdu);
        body.put("HEAD", header);
        body.put("PRO_COD", "000000");//3
        body.put("TTXN_AMT","000000002000");//4
        body.put("CSEQ_NO","100028");//11
        body.put("IN_MOD", "021");//22
        body.put("CON_MOD","00");//25
        body.put("","8A63480514C5DE5306B5C8942C548E3D00000");
        body.put("AUT_CD","000000");//38
        body.put("TRM_NO", posNo);//41
        body.put("MERC_CD", shopCode);//42

        body.put("F47","SI=13|SN=61112015232211|TP=SCL8300|CT=2");//47
        body.put("CCY","156");//49
        body.put("PIN_DATA","F7F2B3B261021B65");
        Date date = new Date();
        String temp53 = TimeUtils.getDateTime(date, "ddHHmmss") + NumberUtil.getHexRandomCode(8);

        body.put("SECUR_INF", temp53);//53
        body.put("RESE_PRI_60", "23" + batch);//60
        body.put("ORI_MES", "000001100026");//61
        body.put("F64","");
        String optionalFields = "3|4|11|22|25|35|38|41|42|47|49|53|60|61|64";
        Iso8583Composer com = new Iso8583Composer();
        byte[] MacMessage = com.compose(mustFields, optionalFields.toString(), TYPE_ID, body, "POSADVANCE", true);
        String request = ByteUtils.byte2HexStr(MacMessage,false);
        String sub = request.substring(22,request.length()-16);
        //63域是否要出现
        String macKey = "A5BDFE6304318A458A629E76E9925DDA";
        String mainKey = "22FA29E3C1B4FE73E050007F01006944";
        String macstr = TestDes.encryptPOSMac(temp53, macKey, sub, mainKey, date);//加密操作,传参问题
        body.put("F64", macstr);
        //生成报文
        System.out.println("大pos签到生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optionalFields, TYPE_ID, body, "POSADVANCE", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage, false);//此处false代表加不加空格
        wf.log("大pos签到请求报文为：" + req, "调试");
        System.out.println("pos签到请求报文为：" + req);
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ip, port);
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("大pos签到响应报文是：" + res);
        wf.log("大pos签到响应报文为：" + res, "调试");
        try {
            //解析报文
            byte[] bytes = ByteUtils.hexStringToByte(res);
            Map<String, String> map = Iso8583Parser.parse("POSADVANCE", bytes, true);
            PosUtil.parse8583("POSADVANCE", res);
            //处理解析的map
            //分别获取39,60,62域
            String bit39 = map.get("39");
            if ("00".equals(bit39)){
                //截取60域批次号部分
                String bit60 = map.get("60");
                String receiveBatch = bit60.substring(2,8);
                String bit62 = map.get("62");
                System.out.println("签到返回的报文为: " + bit62);
            }else {
                System.out.println("返回的39域为: " + bit39);
            }
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("大pos签到返回报文解析报文错误");
            wf.log("大pos签到返回报文解析错误" ,"调试");
        }
    }

}
